Skip to content

fix(gfql/polars): Contains honors regex=/flags= (B1, viz-filter #1673)#1674

Closed
lmeyerov wants to merge 1 commit into
dev/gfql-polars-enginefrom
dev/gfql-polars-contains-regex-fix
Closed

fix(gfql/polars): Contains honors regex=/flags= (B1, viz-filter #1673)#1674
lmeyerov wants to merge 1 commit into
dev/gfql-polars-enginefrom
dev/gfql-polars-contains-regex-fix

Conversation

@lmeyerov

@lmeyerov lmeyerov commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

First increment of the viz-filter → GFQL Cypher conformance work (#1673). Targets the in-flight polars-engine branch (#1660) since the fix is in its filter_by_dict lowering — fold into #1660 or take as a stacked fix, your call.

Bug

The native polars Contains lowering (lazy/engine/polars/predicates.py) always used str.contains(..., literal=False), so a literal request (contains(pat, regex=False)) was still regex-interpreted: a pattern with a metacharacter over-matched. Proven: contains('a.c', regex=False) matches 'abc' on polars but only 'a.c'/'a.c.d' on pandas/cuDF. flags= was also silently dropped.

Fix

  • regex=False → literal match (literal=True); case-insensitive literal folds both sides (matches pandas' result — polars has no literal+case flag).
  • regex mode → maps case=/flags= (IGNORECASE/MULTILINE/DOTALL/VERBOSE) to a Rust-regex inline flag prefix (?ims…).

Why it matters

The viz filter language emits literal CONTAINS/LIKE as well as regex; without this, a literal filter with any regex metacharacter over-matches on polars. Prereq (B1) for the Cypher =~ regex operator landing cross-engine (#1673).

Tests

🤖 Generated with Claude Code

The native polars filter_by_dict lowering of the Contains predicate always
used str.contains(literal=False), so contains(pat, regex=False) was still
regex-interpreted — a literal pattern with a metacharacter over-matched
(contains('a.c', regex=False) matched 'abc'), diverging from pandas/cuDF;
flags= was also dropped. Now regex=False lowers to a literal match
(case-insensitive literal folds both sides to match pandas), and regex mode
maps case=/flags= to a Rust-regex inline flag prefix.

First increment of the viz-filter → GFQL Cypher conformance work (#1673):
the extended Cypher dialect's regex operator must run correctly on polars.

+1 engine-parametrized differential-parity test; ruff + mypy clean;
polars chain + row-pipeline parity suites 150 passed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lmeyerov

lmeyerov commented Jul 2, 2026

Copy link
Copy Markdown
Contributor Author

Folded into #1660 — the Contains regex/flags fix is a fix to #1660's own polars engine code, so it now lives there (cherry-picked as a18c594, same author/content/message, on top of #1660's team-polish commit). #1675's base retargeted to dev/gfql-polars-engine. Part of shrinking the stack (11→9 PRs).

@lmeyerov lmeyerov closed this Jul 2, 2026
@lmeyerov
lmeyerov deleted the dev/gfql-polars-contains-regex-fix branch July 2, 2026 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant